package com.tang.calculator;

import com.tang.calculator.context.CalculateContext;
import com.tang.calculator.symbols.Calculation;
import com.tang.calculator.symbols.Function;
import com.tang.calculator.symbols.OperatorSymbol;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.regex.Pattern;

@Component
public class CheckFormula {
    @Autowired
    List<OperatorSymbol> operatorSymbols;
    @Autowired
    List<Calculation> calculations;
    @Autowired
    List<Function> functions;

    public String check(CalculateContext context) {
        String formula = context.getFormula();
        StringBuilder sb = new StringBuilder();
        //清洗字符串
        String check = cleaning1(formula);
        //判断括号前面有没有数字
        sb.append(notNumber(check) + "\n");
        //判断括号是否对称
        sb.append(symmetry(formula) + "\n");
        //清洗字符串
        check = cleaning2(check);
        //判断运算符是否正确
        sb.append(symbol(context, check) + "\n");
        //去除数字和字符
//        sb.append(irregular(check) + "\n");

        String replace = sb.toString().replace("null\n", "");
        return StringUtils.isEmpty(replace) ? "OK" : replace;
    }

    /**
     * 清洗字符串
     *
     * @param str
     * @return
     */
    public String cleaning1(String str) {
        String replace = str.replace(" ", "").replace(".", "");
        return replace;
    }

    public String cleaning2(String str) {
        for (Function function : functions) {
            if (function.getName().contains("(")) {
                str = str.replace(function.getName(), "(");
            } else if (function.getName().contains(")")) {
                str = str.replace(function.getName(), ")");
            }
        }
        return str;
    }

    /**
     * 检查()是否对称
     *
     * @param str
     * @return
     */
    public String symmetry(String str) {
        int length = str.length();
        int leftSymbol = length - str.replace("(", "").length();
        int rightSymbol = length - str.replace(")", "").length();
        if (leftSymbol != rightSymbol) {
            if (rightSymbol > leftSymbol) return "缺少" + (rightSymbol - leftSymbol) + "个【 ( 】符号";
            if (rightSymbol < leftSymbol) return "缺少" + (leftSymbol - rightSymbol) + "个【 ) 】符号";
        }
        return null;
    }

    /**
     * 判断括号前面有没有数字
     *
     * @param str
     * @return
     */
    public String notNumber(String str) {
        for (OperatorSymbol operatorSymbol : operatorSymbols) {
            String name = operatorSymbol.getName();
            if (name.contains("(")) {
                if (getSubscript(str, name, -1)) return "【" + operatorSymbol.getName() + "】符号前有数字";
            } else if (name.contains(")")) {
                if (getSubscript(str, name, 1)) return "【" + operatorSymbol.getName() + "】符号后有数字";
            }
        }
        return null;
    }

    /**
     * 判断有没有不合规字符
     *
     * @param str
     * @return
     */
    public String irregular(String str) {
        for (OperatorSymbol operatorSymbol : operatorSymbols) {
            String name = operatorSymbol.getName();
            str = str.replace(name, "");
        }
        //判断有没有不合规字符
        for (int i = 0; i <= 9; i++) {
            str = str.replace(i + "", "");
        }
        if (str.length() > 0) {
            return "包含不规则符号" + str;
        }
        return null;
    }

    /**
     * 判断运算符是否规范
     *
     * @param str
     * @return
     */
    public String symbol(CalculateContext context, String str) {
        StringBuffer sb = new StringBuffer();
        for (Calculation calculation : calculations) {
            String check = calculation.check(context, str);
            if (!StringUtils.isEmpty(check)) sb.append(check + "\n");
        }
        if (!StringUtils.isEmpty(sb.toString())) return sb.toString();
        return null;
    }

    /**
     * 判断函数是否正确规范
     *
     * @param str
     * @return
     */
    public String function(String str) {
        return null;
    }

    /**
     * 判断()前后是否有数字
     *
     * @param string
     * @param getString
     * @param subscript
     * @return
     */
    public Boolean getSubscript(String string, String getString, int subscript) {
        int a = getInt(string, getString);
        //"((-10/6+5-1)*(-8)+(1*( 2- 3)+(7 / 8 -6 )+8- 6/ 4 - 5* 3 *( -2))) * 6+sum(1-3,2*2,(sum(1+1)+2)*3)"
        int length = string.length();
        if (a == 0) {
            if (getSubscript(string.substring(getString.length(), length), getString, subscript)) return true;
        } else if (a > 0) {
            String sub = string.substring(a + subscript);
            if (StringUtils.isEmpty(sub)) return false;
            Pattern pattern = Pattern.compile("[0-9]*");
            if (pattern.matcher(sub.substring(0, 1)).matches()) return true;
            if (getSubscript(string.substring(a, length), getString, subscript)) return true;
        }
        return false;
    }

    /**
     * 确定指定字符坐标 没有返回-1
     *
     * @param string
     * @param getString
     * @return
     */
    public static int getInt(String string, String getString) {
        if (string.contains(getString)) {
            for (int i = 0; i < string.length() - getString.length(); i++) {
                if (string.indexOf(getString, i) >= 0) {
                    i = string.indexOf(getString, i);
                    return i;
                }
            }
        }
        return -1;
    }
}
